package com.easyaop.core;

import com.easyaop.api.Context;
import com.easyaop.api.LoggerFactory;
import org.objectweb.asm.Opcodes;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.security.ProtectionDomain;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author lipan
 * @since 2025-01-19
 */
public class AbstractWeaver implements ClassFileTransformer {
    public static final Logger LOGGER = LoggerFactory.getLogger("Weaver");

    private volatile ClassFileTransformer targetTransformer;

    public AbstractWeaver() {
    }

    public void setTargetTransformer(ClassFileTransformer targetTransformer) {
        this.targetTransformer = targetTransformer;
    }

    @Override
    public byte[] transform(ClassLoader loader, String name, Class<?> classBeingRedefined,
                            ProtectionDomain domain, byte[] classBytes) throws IllegalClassFormatException {
        try {
            // 如果不为空可以抛异常
            ClassFileTransformer transformer = this.targetTransformer;
            if (transformer == null) {
                return classBytes;
            }
            String className = name.replace('/', '.');
            if (skip(className)
//                    || !hasPointcut(className)
                    || !Context.hasPointcut(className)
            ) {
                return classBytes;
            }

            byte classByte = classBytes[7];
            if (classByte == 50) {// 把class6转成7
//                System.out.println("class-version "+name);
                classBytes[7] = (byte) Opcodes.V1_7;
//                ClassReader classReader = new ClassReader(classBytes);
//                ClassWriter classWriter = new ClassWriter(classReader,ClassWriter.COMPUTE_FRAMES);
//                VersionChange versionChange = new VersionChange(Opcodes.ASM4, classWriter);
//                classReader.accept(versionChange, ClassReader.EXPAND_FRAMES);
//                classBytes = classWriter.toByteArray();

            }
            //            byte[] transform = doTransform(transformer, loader, name, classBeingRedefined, domain, classBytes);
            byte[] transform = transformer.transform(loader, name, classBeingRedefined, domain, classBytes);


            if (!Context.isTransformed(className)) {
                return classBytes;
            }


            LOGGER.info("weaving " + className + " - "
//                    +transform.hashCode()
            );

            return transform;
        } catch (Throwable e) {

            LOGGER.log(Level.WARNING
                    , "weaving error " + name + " - ", e);
            throw new RuntimeException(e);

        }
    }

    protected byte[] doTransform(ClassFileTransformer transformer, ClassLoader loader, String name,
                                 Class<?> classBeingRedefined,
                                 ProtectionDomain domain, byte[] classBytes) throws IllegalClassFormatException {
        return classBytes;
    }

    public static boolean skip(String className) {
        return className.startsWith("com.easyaop.api.")
                || className.startsWith("com.easyaop.core.")
                || className.startsWith("com.easyaop.asm.")
                || className.startsWith("com.easyaop.commons.")
                || className.startsWith("net.bytebuddy.")
                || className.startsWith("java.")
                || className.startsWith("jdk.")
                || className.startsWith("org.aspectj.")
                || className.startsWith("org.objectweb.asm.")
                || className.startsWith("sun.")
                || className.startsWith("javassist.")
                ;
    }


}
